/*
 * Copyright 2007-2008 Andrew O'Malley
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package ws.quokka.plugin.cobertura;

import net.sourceforge.cobertura.ant.InstrumentTask;
import net.sourceforge.cobertura.ant.MergeTask;
import net.sourceforge.cobertura.ant.ReportTask;

import org.apache.tools.ant.taskdefs.UpToDate;
import org.apache.tools.ant.types.FileSet;

import ws.quokka.core.plugin_spi.support.ResourcesList;
import ws.quokka.core.plugin_spi.support.Setter;
import ws.quokka.core.plugin_spi.support.TypedProperties;

import ws.quokka.plugin.devreport.DevReportHelper;
import ws.quokka.plugin.lifecycle.LifeCycleImpl;

import java.io.File;

import java.util.Iterator;


/**
 *
 */
public class CoberturaPlugin extends LifeCycleImpl {
    //~ Static fields/initializers -------------------------------------------------------------------------------------

    private static final String DATAFILE = "instrument.dataFile";

    //~ Instance fields ------------------------------------------------------------------------------------------------

    private DevReportHelper helper;
    private TypedProperties globalProperties;

    //~ Methods --------------------------------------------------------------------------------------------------------

    //cobertura-check=net.sourceforge.cobertura.ant.CheckTask
    public void initialise() {
        super.initialise();
        helper = new DevReportHelper(getResources(), properties(), log());
        globalProperties = createProperties("q.cobertura.");
    }

    public void instrument() {
        // Test if instrumentation is required before proceeding
        UpToDate upToDate = (UpToDate)utils().init(new UpToDate(), "uptodate");
        upToDate.setTargetFile(getDataFile());

        FileSet classes = properties().getFileSet("classes");
        upToDate.addSrcfiles(classes);

        if (upToDate.eval()) {
            log().verbose("Skipping instrumentation as .ser file is up to date");
        } else {
            utils().delete(getDataFile());

            // Instrument classes
            Setter setter = new Setter(properties());
            InstrumentTask instrument = (InstrumentTask)utils().init(new InstrumentTask(), "cobertura-instrument");
            instrument.setToDir(getLifeCycle().getInstrumentCompiledOutput());
            instrument.addFileset(classes);
            instrument.setDataFile(getDataFile().getAbsolutePath());

            //            setter.set(instrument, new String[] {"maxMemory"});
            instrument.perform();
        }

        // Add the classpath that cobertura requires when running tests
        getLifeCycle().getState().addInstrumentedTestPath(getResources().getPathGroupAsPath("test"));
    }

    public void collect() {
        helper.addResource(properties().getFileSet("src"));
        helper.addResource(DATAFILE, utils().toFileSet(getDataFile()));

        if (properties().getBoolean("propogate")) {
            propogate();
        }
    }

    public void propogate() {
        helper.propogateResources();
        helper.propogateResources(DATAFILE);
    }

    public void report() {
        helper.addReport();
        report(helper.getLocalResources(), getDataFile());
    }

    public void aggregateReport() {
        //        Object resources = getProject().getReference("q.devreport.resources");
        //        System.out.println("resources=" + resources);
        helper.addReport();

        File merged = properties().getFile("mergedDataFile");
        merge(helper.getAggregatedResources(DATAFILE), merged);
        report(helper.getAggregatedResources(), merged);
    }

    protected void report(ResourcesList sources, File data) {
        Setter setter = new Setter(properties());
        ReportTask report = (ReportTask)utils().init(new ReportTask(), "cobertura-report");
        report.setDataFile(data.getAbsolutePath());
        report.setDestDir(properties().getFile("destDir"));
        report.setFormat(properties().getString("format"));

        //        setter.set(report, new String[] {"maxMemory"});
        for (Iterator i = sources.getNested().iterator(); i.hasNext();) {
            report.addFileset((FileSet)i.next());
        }

        report.perform();
        log().info("Generated report to: " + new File(properties().getFile("destDir"), "index.html").getAbsolutePath());
    }

    protected void merge(ResourcesList dataFiles, File merged) {
        // Merge .ser files from sub-projects
        utils().mkdir(merged.getParentFile());
        utils().delete(merged); // Delete or it includes previous runs/merges

        MergeTask merge = (MergeTask)utils().init(new MergeTask(), "cobertura-merge");
        merge.setDataFile(merged.getAbsolutePath());

        for (Iterator i = dataFiles.getNested().iterator(); i.hasNext();) {
            merge.addFileset((FileSet)i.next());
        }

        merge.perform();
    }

    protected File getDataFile() {
        File file = globalProperties.getFile(DATAFILE);

        if (log().isDebugEnabled()) {
            log().debug("dataFile=" + file.getPath());
        }

        return file;
    }
}
